import 'package:agora_rtm/src/impl/gen/rtm_result_handler.dart';
import 'package:agora_rtm/src/impl/extensions.dart';
import 'package:agora_rtm/src/binding_forward_export.dart';
import 'package:agora_rtm/src/bindings/gen/agora_rtm_storage_impl.dart'
    as native_binding;
import 'package:flutter/services.dart';

import 'agora_rtm_client_ohos_impl.dart';

class RtmStorageOhosImpl implements RtmStorage {
  RtmStorageOhosImpl(this._methodChannel,this.rtmResultHandler);

  final MethodChannel _methodChannel;
  final RtmResultHandler rtmResultHandler;

  @override
  Future<(RtmStatus, GetChannelMetadataResult?)> getChannelMetadata(String channelName, RtmChannelType channelType) async {
    final Map<String, dynamic> args = {
      "channelName":channelName,
      "channelType":channelType.value(),
    };
    var code = await _methodChannel.invokeMethod("getChannelMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (GetChannelMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, GetUserMetadataResult?)> getUserMetadata(String userId) async {
    final Map<String, dynamic> args = {
      "userId":userId,
    };
    var code = await _methodChannel.invokeMethod("getUserMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (GetUserMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, RemoveChannelMetadataResult?)> removeChannelMetadata(String channelName, RtmChannelType channelType, {int majorRevision = -1, List<MetadataItem> metadata = const [], bool recordTs = false, bool recordUserId = false, String lockName = ''}) async {
    final Map<String, dynamic> options = {
      "recordTs":recordTs,
      "recordUserId":recordUserId,
    };
    final Map<String, dynamic> args = {
      "channelName":channelName,
      "channelType":channelType.value(),
      "options":jsonEncode(options),
      "localName":lockName,
      "majorRevision":majorRevision,
      "metadata":metadata.map((a)=>a.toJson()).toList(),
    };
    var code = await _methodChannel.invokeMethod("removeChannelMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (RemoveChannelMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, RemoveUserMetadataResult?)> removeUserMetadata(String userId, {int majorRevision = -1, List<MetadataItem> metadata = const [], bool recordTs = false, bool recordUserId = false}) async {
    final Map<String, dynamic> options = {
      "recordTs":recordTs,
      "recordUserId":recordUserId,
    };
    final Map<String, dynamic> args = {
      "userId":userId,
      "options":jsonEncode(options),
      "majorRevision":majorRevision,
      "metadata":metadata.map((a)=>a.toJson()).toList(),
    };
    var code = await _methodChannel.invokeMethod("removeUserMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (RemoveUserMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, SetChannelMetadataResult?)> setChannelMetadata(String channelName, RtmChannelType channelType, List<MetadataItem> metadata, {int majorRevision = -1, bool recordTs = false, bool recordUserId = false, String lockName = ''}) async {
    final Map<String, dynamic> options = {
      "recordTs":recordTs,
      "recordUserId":recordUserId,
    };
    final Map<String, dynamic> args = {
      "channelName":channelName,
      "channelType":channelType.value(),
      "options":jsonEncode(options),
      "localName":lockName,
      "majorRevision":majorRevision,
      "metadata":metadata.map((a)=>a.toJson()).toList(),
    };
    var code = await _methodChannel.invokeMethod("setChannelMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (SetChannelMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, SetUserMetadataResult?)> setUserMetadata(String userId, List<MetadataItem> metadata, {int majorRevision = -1, bool recordTs = false, bool recordUserId = false}) async {
    final Map<String, dynamic> options = {
      "recordTs":recordTs,
      "recordUserId":recordUserId,
    };
    final Map<String, dynamic> args = {
      "userId":userId,
      "options":jsonEncode(options),
      "majorRevision":majorRevision,
      "metadata":metadata.map((a)=>a.toJson()).toList(),
    };
    var code = await _methodChannel.invokeMethod("setUserMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (SetUserMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, SubscribeUserMetadataResult?)> subscribeUserMetadata(String userId) async {
    final Map<String, dynamic> args = {
      "userId":userId,
    };
    var code = await _methodChannel.invokeMethod("subscribeUserMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (SubscribeUserMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, UnsubscribeUserMetadataResult?)> unsubscribeUserMetadata(String userId) async {
    final Map<String, dynamic> args = {
      "userId":userId,
    };
    var code = await _methodChannel.invokeMethod("unsubscribeUserMetadata", args);
    return (RtmClientOhosImpl.getRtmStatus(code),null);
  }

  @override
  Future<(RtmStatus, UpdateChannelMetadataResult?)> updateChannelMetadata(String channelName, RtmChannelType channelType, List<MetadataItem> metadata, {int majorRevision = -1, bool recordTs = false, bool recordUserId = false, String lockName = ''}) async {
    final Map<String, dynamic> options = {
      "recordTs":recordTs,
      "recordUserId":recordUserId,
    };
    final Map<String, dynamic> args = {
      "channelName":channelName,
      "channelType":channelType.value(),
      "options":jsonEncode(options),
      "localName":lockName,
      "majorRevision":majorRevision,
      "metadata":metadata.map((a)=>a.toJson()).toList(),
    };
    var code = await _methodChannel.invokeMethod("updateChannelMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (UpdateChannelMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }

  @override
  Future<(RtmStatus, UpdateUserMetadataResult?)> updateUserMetadata(String userId, List<MetadataItem> metadata, {int majorRevision = -1, bool recordTs = false, bool recordUserId = false}) async {
    final Map<String, dynamic> options = {
      "recordTs":recordTs,
      "recordUserId":recordUserId,
    };
    final Map<String, dynamic> args = {
      "userId":userId,
      "options":jsonEncode(options),
      "majorRevision":majorRevision,
      "metadata":metadata.map((a)=>a.toJson()).toList(),
    };
    var code = await _methodChannel.invokeMethod<String>("setUserMetadata", args);
    Map<String,dynamic> map = jsonDecode(code!);
    final (UpdateUserMetadataResult result, RtmErrorCode errorCode) = await rtmResultHandler.request(int.parse(map['requestId']));
    return (RtmClientOhosImpl.getRtmStatus(map['errorCode']),result);
  }
}
